package com.groupbuying.storeinternal.service.impl;

import com.groupbuying.storeinternal.connector.FileFegin;
import com.groupbuying.storeinternal.connector.SysconfigFeign;
import com.groupbuying.storeinternal.constants.CommonConstants;
import com.groupbuying.storeinternal.dao.StoreShopDao;
import com.groupbuying.storeinternal.domain.StoreRecommendDO;
import com.groupbuying.storeinternal.domain.StoreShopDO;
import com.groupbuying.storeinternal.dto.StorePhotoDTO;
import com.groupbuying.storeinternal.dto.StoreShopPageDTO;
import com.groupbuying.storeinternal.dto.forExternal.StoreShopDTO;
import com.groupbuying.storeinternal.dto.forExternal.do2dto.StoreShopConvert;
import com.groupbuying.storeinternal.service.StoreMainInfoService;
import com.groupbuying.storeinternal.service.StoreOpexRuleRelService;
import com.groupbuying.storeinternal.service.StoreRecommendService;
import com.groupbuying.storeinternal.service.StoreShopService;
import com.groupbuying.storeinternal.utils.DistanceUtils;
import com.groupbuying.storeinternal.utils.GeoHashUtils;
import com.groupbuying.storeinternal.utils.R;
import com.groupbuying.storeinternal.utils.RedisUtils;
import com.groupbuying.storeinternal.utils.apiresult.JsonUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
@Transactional
public class StoreShopServiceImpl implements StoreShopService {
    @Autowired
    private StoreShopDao storeShopDao;
    @Autowired
    private FileFegin fileFegin;
    @Autowired
    private SysconfigFeign sysconfigFeign;
    @Autowired
    private StoreRecommendService storeRecommendService;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private StoreOpexRuleRelService storeOpexRuleRelService;

    @Value("${download.url}")
    private String downLoadUrl;

    private static Logger log = LoggerFactory.getLogger(StoreShopServiceImpl.class);


    @Override
    public StoreShopDO get(String uuid) {
        return storeShopDao.get(uuid);
    }

    @Override
    public List<StoreShopDO> list(Map<String, Object> map) {
        return storeShopDao.list(map);
    }

    @Override
    public int count(Map<String, Object> map) {
        return storeShopDao.count(map);
    }

    @Override
    public int save(StoreShopDO storeShop) {
        return storeShopDao.save(storeShop);
    }

    @Override
    public int update(StoreShopDO storeShop) {
        return storeShopDao.update(storeShop);
    }

    @Override
    public int remove(String uuid) {
        return storeShopDao.remove(uuid);
    }

    @Override
    public int batchRemove(String[] uuids) {
        return storeShopDao.batchRemove(uuids);
    }


    @Override
    public R getShopList(Map<String, Object> params) {
        Object temp = params.get("longitude");
        Double longitude = temp != null ? Double.parseDouble(temp.toString()) : null;
        temp = params.get("latitude");
        Double latitude = temp != null ? Double.parseDouble(temp.toString()) : null;
        // 每页显示的条数
        temp = params.get("pageShow");
        Integer pageShow = temp != null ? Integer.parseInt(temp.toString()) : null;

        temp = params.get("level");
        Integer level = temp != null ? Integer.parseInt(temp.toString()) : null;

        if (longitude == null || latitude == null || pageShow == null || pageShow == 0 || level == null) {
            return R.error("params is null");
        }

        //获取
        String geoCode = GeoHashUtils.getGeoHash(latitude, longitude, level);
        String[] geoCodes = GeoHashUtils.getAdjacent(latitude, longitude, level);
        Map<String, Object> map = new HashMap<>();
        for (int i = 0; i < geoCodes.length; i++) {
            map.put("geoCode" + (i + 1), geoCodes[i]);
        }
        map.put("geoCode9", geoCode);
        map.put("level", level);

        List<StoreShopDO> queryList = storeShopDao.queryListByGeoHash(map);

        if (!(queryList.size() > 0)) {
            return R.data(new StoreShopPageDTO(0, 0, pageShow, new ArrayList<>()));
        }

        //保存距离 修改图片地址
        List<Map<String, Object>> shopList = new ArrayList<>();
        dealStoreData(longitude, latitude, queryList, shopList);
        //分页
        return R.data(getPagedList(shopList, pageShow));
    }

    @Override
    public Object searchShopListByCategoryOrStoreName(Map<String, Object> params) {
        Object temp = params.get("longitude");
        Double longitude = temp != null ? Double.parseDouble(temp.toString()) : null;
        temp = params.get("latitude");
        Double latitude = temp != null ? Double.parseDouble(temp.toString()) : null;
        // 每页显示的条数
        temp = params.get("pageShow");
        Integer pageShow = temp != null ? Integer.parseInt(temp.toString()) : null;
        // 品类名称
        temp = params.get("categoryName");
        String categoryName = temp != null ? temp.toString() : null;
        // 部分品类名称 用于模糊匹配
        temp = params.get("categoryNamePart");
        String categoryNamePart = temp != null ? temp.toString() : null;
        // 商户名称
        temp = params.get("storeName");
        String storeName = temp != null ? temp.toString() : null;
        // 商户名称
        temp = params.get("storeNameOrCategoryNamePart");
        String storeNameOrCategoryNamePart = temp != null ? temp.toString() : null;

        if ( pageShow == null || pageShow == 0) {
            return R.error("params is null");
        }

        //获取
        Map map = new HashMap();
        map.put("categoryName", categoryName);
        map.put("storeName", storeName);
        map.put("categoryNamePart", categoryNamePart);
        map.put("storeNameOrCategoryNamePart", storeNameOrCategoryNamePart);
        //获取商家数据
        List<StoreShopDO> queryList = storeShopDao.searchShopListByCategoryOrStoreName(map);

        if (!(queryList.size() > 0)) {
            return R.data(new StoreShopPageDTO(0, 0, pageShow, new ArrayList<>()));
        }

        //保存距离 修改图片地址
        List<Map<String, Object>> shopList = new ArrayList<>();
        dealStoreData(longitude, latitude, queryList, shopList);
        //分页
        return R.data(getPagedList(shopList, pageShow));
    }

    @Override
    public Object getRecommendStoreList(Map<String, Object> params) {


        Object temp = params.get("longitude");
        Double longitude = temp != null ? Double.parseDouble(temp.toString()) : null;
        temp = params.get("latitude");
        Double latitude = temp != null ? Double.parseDouble(temp.toString()) : null;

        // 有缓存
        Object redisData = redisUtils.getValue("store_recommend");
        if (redisData != null) {
            List<Map<String, Object>> list = (List<Map<String, Object>>) JsonUtils.convertBean(redisData.toString(), List.class);
            //只处理距离和排序
            dealStoreData(longitude, latitude, list);
            return R.data(list);
        }


        //获取商家数据
        List<StoreShopDO> queryList = storeShopDao.getRecommendStoreList(params);
        if (!(queryList.size() > 0)) {
            return R.data(new ArrayList<>());
        }
        //保存距离 修改图片地址
        List<Map<String, Object>> shopList = new ArrayList<>();
        dealStoreDataAndScore(longitude, latitude, queryList, shopList);

        redisUtils.setKey("store_recommend", JsonUtils.beanToJson(shopList), 60 * 60 * 24);

        //分页
        return R.data(shopList);
    }

    @Override
    public StoreShopDO getByStoreUuid(String storeUuid) {
        Map map = new HashMap();
        map.put("delflag", CommonConstants.COMMON_FLAG_UNDEL);
        map.put("storeuuid", storeUuid);
        List<StoreShopDO> list = storeShopDao.list(map);
        return list != null && list.size() > 0 ? list.get(0) : null;
    }

    @Override
    public Object clearRecommendCache() {

        try {
            redisUtils.delKey("store_recommend");
        } catch (Exception e) {
            e.printStackTrace();
            R.error();
        }

        return R.ok();
    }


    public void getOpexRule(Map<String, Object> shop, String storeUuid) {
        String ruleId = storeOpexRuleRelService.getOpexRuleByStoreID(storeUuid);
        Map ruleMap = new HashMap();
        ruleMap.put("ruleId", ruleId);
        ruleMap.put("delFlag", CommonConstants.COMMON_FLAG_UNDEL);
        Map ruleRes = sysconfigFeign.getStoreOpexRule(ruleMap);
        if (ruleRes != null) {
            BigDecimal backCurrency = new BigDecimal(ruleRes.get("backCurrencyRatio").toString());
            BigDecimal discount = new BigDecimal(ruleRes.get("currencyPayDiscount").toString());
            discount = discount.divide(new BigDecimal(10));
            shop.put("ratio", backCurrency);
            shop.put("discount", discount);
            shop.put("ruleId", ruleId);
        }
    }

    public void dealStoreDataAndScore(Double longitude, Double latitude, List<StoreShopDO> storeShopList, List<Map<String, Object>> shopList) {
        Map<String, Object> shopMap;
        Map<String, Object> queryParam = new HashMap<>();
        if (longitude == null || latitude == null) {
            for (StoreShopDO storeShop : storeShopList) {


                StorePhotoDTO storePhotoDTO = new StorePhotoDTO();
                String slideshow = storeShop.getSlideshow();
                storePhotoDTO.setSlideshow(StringUtils.isNotBlank(slideshow)?fileFegin.getDownloadUrlByFileGroupKey(slideshow):new ArrayList<>(0));
                String doorphoto = storeShop.getDoorphoto();
                storePhotoDTO.setDoorPhoto(StringUtils.isNotBlank(doorphoto)?fileFegin.getDownloadUrlByFileGroupKey(doorphoto):new ArrayList<>(0) );
                String withinphoto = storeShop.getWithinphoto();
                storePhotoDTO.setWithinPhoto(StringUtils.isNotBlank(withinphoto)?fileFegin.getDownloadUrlByFileGroupKey(withinphoto): new ArrayList<>(0));                shopMap = new HashMap<>();

                shopMap = new HashMap<>();
                shopMap.put("shop", StoreShopConvert.MAPPER.doToDTO(storeShop));
                shopMap.put("distanceStr",">5km");
                shopMap.put("photo", storePhotoDTO);

                queryParam.put("storeuuid", storeShop.getStoreuuid());
                StoreRecommendDO storeRecommendDO = storeRecommendService.list(queryParam).get(0);
                shopMap.put("score",storeRecommendDO.getScore());
                //商户积分规则
                getOpexRule(shopMap, storeShop.getStoreuuid());
                shopList.add(shopMap);
            }
        }else {
            for (StoreShopDO storeShop : storeShopList) {

                StorePhotoDTO storePhotoDTO = new StorePhotoDTO();
                String slideshow = storeShop.getSlideshow();
                storePhotoDTO.setSlideshow(StringUtils.isNotBlank(slideshow)?fileFegin.getDownloadUrlByFileGroupKey(slideshow):new ArrayList<>(0));
                String doorphoto = storeShop.getDoorphoto();
                storePhotoDTO.setDoorPhoto(StringUtils.isNotBlank(doorphoto)?fileFegin.getDownloadUrlByFileGroupKey(doorphoto):new ArrayList<>(0) );
                String withinphoto = storeShop.getWithinphoto();
                storePhotoDTO.setWithinPhoto(StringUtils.isNotBlank(withinphoto)?fileFegin.getDownloadUrlByFileGroupKey(withinphoto): new ArrayList<>(0));                shopMap = new HashMap<>();

                shopMap.put("shop", StoreShopConvert.MAPPER.doToDTO(storeShop));
                Double distance = DistanceUtils.getDistance(longitude, latitude, storeShop.getLgt().doubleValue(), storeShop.getLat().doubleValue());
                shopMap.put("distanceStr",  DistanceUtils.formatDistance(distance));
                shopMap.put("distance",  distance);
                shopMap.put("photo", storePhotoDTO);

                queryParam.put("storeuuid", storeShop.getStoreuuid());
                StoreRecommendDO storeRecommendDO = storeRecommendService.list(queryParam).get(0);
                shopMap.put("score",storeRecommendDO.getScore());
                //商户积分规则
                getOpexRule(shopMap, storeShop.getStoreuuid());
                shopList.add(shopMap);
            }

        }


    }

    public void dealStoreData(Double longitude, Double latitude, List<StoreShopDO> storeShopList, List<Map<String, Object>> shopList) {
        Map<String, Object> shopMap;
        if (longitude == null || latitude == null) {
            for (StoreShopDO storeShop : storeShopList) {

                StorePhotoDTO storePhotoDTO = new StorePhotoDTO();
                String slideshow = storeShop.getSlideshow();
                storePhotoDTO.setSlideshow(StringUtils.isNotBlank(slideshow)?fileFegin.getDownloadUrlByFileGroupKey(slideshow):new ArrayList<>(0));
                String doorphoto = storeShop.getDoorphoto();
                storePhotoDTO.setDoorPhoto(StringUtils.isNotBlank(doorphoto)?fileFegin.getDownloadUrlByFileGroupKey(doorphoto):new ArrayList<>(0) );
                String withinphoto = storeShop.getWithinphoto();
                storePhotoDTO.setWithinPhoto(StringUtils.isNotBlank(withinphoto)?fileFegin.getDownloadUrlByFileGroupKey(withinphoto): new ArrayList<>(0));                shopMap = new HashMap<>();

                shopMap = new HashMap<>();
                shopMap.put("shop", StoreShopConvert.MAPPER.doToDTO(storeShop));
                shopMap.put("distanceStr",">5km");
                shopMap.put("photo", storePhotoDTO);
                shopMap.put("score","5");
                //商户积分规则
                getOpexRule(shopMap, storeShop.getStoreuuid());
                shopList.add(shopMap);
            }
        }else {
            for (StoreShopDO storeShop : storeShopList) {

                StorePhotoDTO storePhotoDTO = new StorePhotoDTO();
                String slideshow = storeShop.getSlideshow();
                storePhotoDTO.setSlideshow(StringUtils.isNotBlank(slideshow)?fileFegin.getDownloadUrlByFileGroupKey(slideshow):new ArrayList<>(0));
                String doorphoto = storeShop.getDoorphoto();
                storePhotoDTO.setDoorPhoto(StringUtils.isNotBlank(doorphoto)?fileFegin.getDownloadUrlByFileGroupKey(doorphoto):new ArrayList<>(0) );
                String withinphoto = storeShop.getWithinphoto();
                storePhotoDTO.setWithinPhoto(StringUtils.isNotBlank(withinphoto)?fileFegin.getDownloadUrlByFileGroupKey(withinphoto): new ArrayList<>(0));                shopMap = new HashMap<>();

                shopMap = new HashMap<>();
                shopMap.put("shop", StoreShopConvert.MAPPER.doToDTO(storeShop));
                Double distance = DistanceUtils.getDistance(longitude, latitude, storeShop.getLgt().doubleValue(), storeShop.getLat().doubleValue());
                shopMap.put("distanceStr", DistanceUtils.formatDistance(distance));
                shopMap.put("distance", distance);
                shopMap.put("photo", storePhotoDTO);
                shopMap.put("score","5");
                //商户积分规则
                getOpexRule(shopMap, storeShop.getStoreuuid());
                shopList.add(shopMap);
            }
            //排序
            storeSort(shopList);

        }


    }

    public void dealStoreData(Double longitude, Double latitude, List<Map<String, Object>> shopList) {

        Map<String, Object> param = new HashMap();
        param.put("isDelete", CommonConstants.COMMON_FLAG_UNDEL);
        if (longitude == null || latitude == null) {
            for (Map<String, Object> storeShop : shopList) {
                String shopStr = JsonUtils.beanToJson(storeShop.get("shop"));
                StoreShopDTO storeShopDTO = JsonUtils.convertBean(shopStr, StoreShopDTO.class);
                log.error("推荐商店信息：{}",storeShopDTO.toString());
                storeShop.put("distanceStr",">5km");

                //获取积分规则
                getOpexRule(storeShop, storeShopDTO.getStoreUuid());

                param.put("storeuuid", storeShopDTO.getStoreUuid());
                StoreRecommendDO storeRecommendDO = storeRecommendService.list(param).get(0);
                storeShop.put("score", storeRecommendDO.getScore());
            }

        } else {

            for (Map<String, Object> storeShop : shopList) {

                String shopStr = JsonUtils.beanToJson(storeShop.get("shop"));
                StoreShopDTO storeShopDTO = JsonUtils.convertBean(shopStr, StoreShopDTO.class);
                log.error("推荐商店信息：{}",storeShopDTO.toString());
                Double distance = DistanceUtils.getDistance(longitude, latitude, storeShopDTO.getLongitude().doubleValue(), storeShopDTO.getLatitude().doubleValue());
                storeShop.put("distanceStr", DistanceUtils.formatDistance(distance));
                storeShop.put("distance",distance);
                //获取积分规则
                getOpexRule(storeShop, storeShopDTO.getStoreUuid());
                param.put("storeuuid", storeShopDTO.getStoreUuid());
                StoreRecommendDO storeRecommendDO = storeRecommendService.list(param).get(0);
                storeShop.put("score", storeRecommendDO.getScore());
            }

        }
    }


    public void storeSort(List<Map<String, Object>> shopList) {
        Map<String, Object> shopMap;
        for (int i = shopList.size() - 1; i > 0; i--) {
            boolean flag = true;
            for (int j = 0; j < i; j++) {
                double distanceA = Double.parseDouble(shopList.get(j).get("distance").toString());
                double distanceB = Double.parseDouble(shopList.get(j + 1).get("distance").toString());
                if (distanceA > distanceB) {
                    shopMap = shopList.get(j);
                    shopList.set(j, shopList.get(j + 1));
                    shopList.set(j + 1, shopMap);
                    flag = false;
                }
            }
            if (flag) {
                break;
            }
        }
    }


    private StoreShopPageDTO getPagedList(List<Map<String, Object>> data, int pageShow) {
        int dataSize = data.size();
        int pageTotal = Double.valueOf(Math.ceil((double) dataSize / (double) pageShow)).intValue();
        List<List<Map<String, Object>>> pageData = new ArrayList();
        for (int pageNum = 0; pageNum < pageTotal; pageNum++) {

            int fromIndex = pageNum * pageShow;
            if (fromIndex >= dataSize) {
                return null;
            }

            int toIndex = (pageNum + 1) * pageShow;
            if (toIndex >= data.size()) {
                toIndex = data.size();
            }
            pageData.add(data.subList(fromIndex, toIndex));
        }
        StoreShopPageDTO dto = new StoreShopPageDTO(dataSize, pageTotal, pageShow, pageData);
        return dto;
    }

}
